import { HvigorNode } from "@ohos/hvigor";
import { OhosModuleContext } from "@ohos/hvigor-ohos-plugin/src/plugin/context/plugin-context";
import path from "path";

export interface RouterServiceMap {
  service?: ServiceConfig;
  router?: RouterConfig;
}

export interface ServiceConfig {
  infos?: ServiceInfo[];
}

export interface Metadata {
  metadata: string;
}

export interface ServiceInfo extends Metadata {
  serviceName: string;
  singleton?: boolean;
  modulePath?: string;
  moduleName?: string;
  className: string;
}

interface RouterInterceptorConfig extends ServiceInfo {}

export interface RouterUriMetadata {
  name?: string;
  host?: string;
  path?: string;
  scheme?: string;
  regex?: RegExp;
  interceptors?: string[];
}

export interface RouterUriConfig {
  type: "component" | "uriHandler";
  imports: {
    name: string;
    path: string;
    isDefault: boolean;
  };
  metadata: RouterUriMetadata;
}

export interface RouterConfig {
  interceptors: RouterInterceptorConfig[];
  routerUris: RouterUriConfig[];
}

export default class RouterServiceConfig {
  private config: RouterServiceMap = {
    service: { infos: [] },
    router: { interceptors: [], routerUris: [] },
  };

  constructor(private context: OhosModuleContext, private node: HvigorNode) {}

  pushRouterUri(params: RouterUriConfig) {
    this.config.router.routerUris.push({
      ...params,
    });
  }

  pushInterceptor(params: {
    name: string;
    className: string;
    classFilePath: string;
    metadata: string;
  }) {
    this.config.router.interceptors.push({
      serviceName: params.name,
      moduleName: this.node.getNodeName(),
      modulePath: params.classFilePath,
      className: params.className,
      singleton: true,
      metadata: params.metadata,
    });
  }

  pushServiceInfo(params: {
    serviceName: string;
    className: string;
    classFilePath: string;
    singleton?: boolean;
    metadata: string;
  }) {
    this.config.service.infos.push({
      serviceName: params.serviceName,
      moduleName: this.node.getNodeName(),
      modulePath: params.classFilePath,
      className: params.className,
      singleton: params.singleton,
      metadata: params.metadata,
    });
  }

  getRuntimeOnlySources(): string[] {
    const infos = this.config.service.infos;
    const interceptors = this.config.router.interceptors;

    return [
      ...new Set(
        [...infos, ...interceptors].map(
          ({ modulePath, moduleName }) =>
            `./${path.relative(moduleName, modulePath)}`
        )
      ),
    ];
  }

  getRouterMap(): object[] {

    const routerMap = [];
    const infos = this.config.service.infos;
    const interceptors = this.config.router.interceptors;

    [...infos, ...interceptors].forEach((info, index) => {
      routerMap.push({
        name: `__nl_service_loader__${this.node.getNodeName()}__${info.moduleName}__${index}`,
        pageSourceFile: info.modulePath.substring(1, info.modulePath.length),
        buildFunction: "",
        customData: {
          __nlServiceName__: info.serviceName,
          __nlClassName__: info.className,
          __nlModuleName__: info.moduleName,
          __nlModulePath__: info.modulePath.replace(/\.(ts|ets)$/, ""),
          __nlClassSingleton__: info.singleton ?? true,
          __nlDecoratorMetadata: info.metadata,
        },
      });
    });

    return routerMap;
  }

  toString(): string {
    return JSON.stringify(this.config);
  }

  getConfig(): RouterServiceMap {
    return this.config;
  }
}
